package com.jinyou.utils.common;

import lombok.extern.slf4j.Slf4j;
import o2o.business.dispatch.DispatchInfo;
import o2o.cache.order.postman.PostmanOrderMemoryMan;
import o2o.cache.postman.PostmanPositionMemory;
import o2o.config.dao.utils.Order;
import o2o.dao.PO.order.OrderInfo;
import o2o.dao.PO.postman.PostmanPositionInfo;
import o2o.postman.model.CityPostman;
import o2o.web.actions.postman.PostmanAction;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.poi.ss.formula.functions.T;

import java.util.*;
import java.util.stream.Collectors;

//list 排序
@Slf4j
public class JYListSort {

    /**
     * List 元素的多个属性进行排序。例如 JYListSort.sort(list, "name", "age")，则先按
     * name 属性排序，name 相同的元素按 age 属性排序。
     * 数字小的在前
     *
     * @param list       包含要排序元素的 List
     * @param properties 要排序的属性。前面的值优先级高。
     */
    public static <V> void sort(List<V> list, final String... properties) {
        Collections.sort(list, new Comparator<V>() {
            public int compare(V o1, V o2) {
                if (o1 == null && o2 == null) return 0;
                if (o1 == null) return -1;
                if (o2 == null) return 1;

                for (String property : properties) {
                    Comparator c = new BeanComparator(property);
                    int result = c.compare(o1, o2);
                    if (result != 0) {
                        return result;
                    }
                }
                return 0;
            }
        });
    }
    /**
     * List 元素的多个属性进行排序。例如 JYListSort.sort(list, "name", "age")，则先按
     * name 属性排序，name 相同的元素按 age 属性排序。
     * 数字小的在前
     *
     * @param list       包含要排序元素的 List
     * @param properties 要排序的属性。前面的值优先级高。
     */
    public static <V> void sortDesc(List<V> list, final String... properties) {
        Collections.sort(list, new Comparator<V>() {
            public int compare(V o1, V o2) {
                if (o1 == null && o2 == null) return 0;
                if (o1 == null) return -1;
                if (o2 == null) return 1;

                for (String property : properties) {
                    Comparator c = new BeanComparator(property);
                    int result = c.compare(o2, o1);
                    if (result != 0) {
                        return result;
                    }
                }
                return 0;
            }
        });
    }


    /**
     * 排序 骑手当前位置到最近收货地址的直线距离 +
     * 最近收货地址到下一个最近收货地址直线距离 +
     * …… +
     * 最后一个订单收货地址到门店的距离，将结果按最小值排序
     * @param disList 骑手集合
     */
    public static void sortDistance(List<DispatchInfo> disList) {

        // 取出骑手
        List<CityPostman> postmanList = disList.stream().map(e -> e.getPostmanInfo()).collect(Collectors.toList());
        List<DispatchInfo> dispatchInfoList = new ArrayList<>();
        if(postmanList.isEmpty()){
            return;
        }
        // 取出骑手身上待配送订单
        for(int i=0 ; i < postmanList.size() ; i++) {
            DispatchInfo dispatchInfo = new DispatchInfo();
            double distance = 0;
            List<OrderInfo> orderInfoList = PostmanOrderMemoryMan.listOfPostmanGrab(postmanList.get(i).getUsername(), 0l, 0, 0);
            PostmanPositionInfo positionInfo = PostmanPositionMemory.getInstance().get(postmanList.get(i).getId());

            // 按离骑手最近距离排序
            orderInfoList.sort((o1,o2)->{
                double distanceo1 = Geohash.distance(positionInfo.getLng(),positionInfo.getLat(),o1.getLng(),o1.getLat());
                double distanceo2 = Geohash.distance(positionInfo.getLng(),positionInfo.getLat(),o2.getLng(),o2.getLat());
                return (int) (distanceo1 - distanceo2);
            });

            for (int v = 0; v < orderInfoList.size(); v++) {
                OrderInfo oiNow = orderInfoList.get(v);
                OrderInfo oiNext = null;
                if (orderInfoList.size() - v != 1) {
                    oiNext = orderInfoList.get(v + 1);
                }
                // 第一次是从骑手位置=>最近收货地址
                // ... 收货位置到下一个收货位置
                // 倒数第一个位置到门店位置;
                if (v == 0) {
                    distance += Geohash.distance(positionInfo.getLat(), positionInfo.getLng(), oiNow.getLat(), oiNow.getLng());
                    log.info("骑手："+postmanList.get(i).getId()+",当前位置到最近收货地址的距离："+distance);

                    if(orderInfoList.size() == 1){
                        distance += Geohash.distance(oiNow.getLat(),oiNow.getLng(),oiNow.getShopLat(),oiNow.getShopLng());
                        log.info("骑手："+postmanList.get(i).getId()+",最后一单订单的收货地址到门店的距离为"+
                                Geohash.distance(oiNow.getLat(),oiNow.getLng(),oiNow.getShopLat(),oiNow.getShopLng()));
                    }
                } else {
                    if(oiNext != null){
                        distance += Geohash.distance(oiNow.getLat(), oiNow.getLng(), oiNext.getLat(), oiNext.getLng());
                        log.info("骑手："+postmanList.get(i).getId()+",身上订单:"+oiNow.getOrderNo()+"到下一个订单"+oiNext.getOrderNo()+"的距离为："+
                                Geohash.distance(oiNow.getLat(), oiNow.getLng(), oiNext.getLat(), oiNext.getLng()));
                    }else{
                        distance += Geohash.distance(oiNow.getLat(),oiNow.getLng(),oiNow.getShopLat(),oiNow.getShopLng());
                        log.info("骑手："+postmanList.get(i).getId()+",最后一单订单的收货地址到门店的距离为"+
                                Geohash.distance(oiNow.getLat(),oiNow.getLng(),oiNow.getShopLat(),oiNow.getShopLng()));
                    }
                }
            }
            log.info("骑手："+postmanList.get(i).getId()+",计算总距离："+distance);
            dispatchInfo.setPostmanInfo(postmanList.get(i));
            dispatchInfo.setDistance(distance);
            dispatchInfoList.add(dispatchInfo);
        }
        //根据距离当中距离排序
        JYListSort.sort(dispatchInfoList, "distance");
        //TODO 此用法会造成原disList其他值被清空
        disList.clear();
        disList.addAll(dispatchInfoList);

    }


    public static void main(String[] args) {

        List<OrderInfo> orderInfoList = new ArrayList<>();

        OrderInfo orderInfo2 = new OrderInfo();
        orderInfo2.setCreateTime(System.currentTimeMillis());
        orderInfo2.setAgentPostmanOverTime(50);
        orderInfoList.add(orderInfo2);

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setCreateTime(System.currentTimeMillis());
        orderInfo.setAgentPostmanOverTime(30);
        orderInfoList.add(orderInfo);

        orderInfoList.forEach(System.out::println);

        orderInfoList.sort((o1,o2)->{
            int agentPostmanOverTime1 = o1.getAgentPostmanOverTime();
            long createTime1 = o1.getCreateTime();
            long o1Time = createTime1 + (agentPostmanOverTime1 * 60 * 1000);

            int agentPostmanOverTime2 = o2.getAgentPostmanOverTime();
            long createTime2 = o2.getCreateTime();
            long o2Time = createTime2 + (agentPostmanOverTime2 * 60 * 1000);
            return (int) (o1Time - o2Time);
        });


        orderInfoList.forEach(System.out::println);

    }


    /**
     * 使用 Map按key进行排序
     * @param map
     * @return
     */
    public static <T> Map<Integer, T> sortMapByKey(Map<Integer, T> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        Map<Integer, T> sortMap = new TreeMap<>(
                new MapKeyComparator());

        sortMap.putAll(map);
        return sortMap;
    }
}

class MapKeyComparator implements Comparator<Integer> {

    @Override
    public int compare(Integer o1, Integer o2) {
        return o1 - o2;
    }
}
